package com.lib.common.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Handler;
import android.os.Message;

import androidx.annotation.NonNull;
import androidx.viewpager.widget.ViewPager;

import android.util.AttributeSet;
import android.view.View;
import android.view.animation.Interpolator;
import android.widget.Scroller;

import com.lib.common.R;

import java.lang.reflect.Field;

/**
 * @author 一叶丶枫凌
 * Created on 2016-11-26 20:19
 */
public class IndicatorView extends View implements ViewPager.OnPageChangeListener {

    private static final int STYLE_CIRCLE = 0x0;
    private static final int STYLE_RECTANGLE = 0x1;
    private static final int STYLE_SQUARE = 0x2;
    private static final int DEFAULT_RADIUS = 6;
    private static final int SELECTED_RADIUS = 9;

    private Paint mPaint = new Paint();
    private int mIndicatorStyle;
    private int mDefaultColor;
    private int mSelectedColor;
    private int mDefaultRadius;
    private int mSelectedRadius;
    private int mCount = 3;
    private int mScrollIntervalMillis = 2500;
    private int mCurrentItem;
    private ViewPager mViewPager;
    private boolean mIsInfinite;
    private boolean mAutoScroll = true;
    private boolean mEnable = true;

    private Handler mHandler = new Handler() {

        @Override
        public void handleMessage(Message msg) {

            if (mEnable) {
                if (mViewPager != null) {
                    if (mIsInfinite) {
                        mViewPager.setCurrentItem(mCurrentItem + 1);
                    } else {
                        mViewPager.setCurrentItem((mCurrentItem + 1) % mCount);
                    }
                }
                startScroll();
            }
        }
    };

    public IndicatorView(Context context) {
        this(context, null);
    }

    public IndicatorView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public IndicatorView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.IndicatorView);
        mAutoScroll = ta.getBoolean(R.styleable.IndicatorView_autoScroll, true);
        mDefaultColor = ta.getColor(R.styleable.IndicatorView_defaultIndicatorColor, Color.LTGRAY);
        mSelectedColor = ta.getColor(R.styleable.IndicatorView_selectedIndicatorColor, getResources().getColor(R.color.theme_color));
        mDefaultRadius = ta.getInt(R.styleable.IndicatorView_defaultRadius, DEFAULT_RADIUS);
        mSelectedRadius = ta.getInt(R.styleable.IndicatorView_selectedRadius, SELECTED_RADIUS);
        mIndicatorStyle = ta.getInt(R.styleable.IndicatorView_indicatorStyle, STYLE_CIRCLE);
        mScrollIntervalMillis = ta.getInt(R.styleable.IndicatorView_scrollIntervalMillis, mScrollIntervalMillis);
        ta.recycle();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        if (widthMode == MeasureSpec.AT_MOST) {
            widthSize = (mCount + 1) * (2 * mDefaultRadius + 5);
        }
        if (heightMode == MeasureSpec.AT_MOST) {
            heightSize = mSelectedRadius * 3;
        }
        setMeasuredDimension(widthSize, heightSize);
    }

    /**
     * @param viewPager          设置要控制滚动的ViewPager
     * @param realViewPagerCount 如果ViewPager的子页面个数超过20，此参数才有用
     */
    public void setViewPager(@NonNull ViewPager viewPager, int realViewPagerCount) {

        if (viewPager.getAdapter() == null) {
            throw new NullPointerException(" This method must be invoked after setAdapter()!!! ");
        }
        mViewPager = viewPager;
        mViewPager.setPageMargin(6);
        mViewPager.setPageTransformer(true, new CubeTransformer());
        mViewPager.addOnPageChangeListener(this);
        int count = mViewPager.getAdapter().getCount();
        if (count > 0 && count <= 19) {
            mCount = count;
        } else {
            mIsInfinite = true;
            mCount = realViewPagerCount > 0 ? realViewPagerCount : 0;
        }
        requestLayout();
        try {
            Field field = ViewPager.class.getDeclaredField("mScroller");
            field.setAccessible(true);
            FixedScroller scroller = new FixedScroller(getContext());
            field.set(mViewPager, scroller);
        } catch (Exception ignored) {
        }
    }

    public void setSelectedColor(int selectedColor) {

        mSelectedColor = selectedColor;
        invalidate();
    }

    public void setDefaultColor(int defaultColor) {

        mDefaultColor = defaultColor;
        invalidate();
    }

    /**
     * 滚动间隔，间隔越小，滚动越快
     *
     * @param millis 间隔时间，单位毫秒
     */
    public void setScrollIntervalMillis(int millis) {

        if (millis < 0) {
            millis = 0;
        }
        mScrollIntervalMillis = millis;
    }

    @Override
    protected void onDraw(Canvas canvas) {

        if (mCount == 0) {
            setVisibility(GONE);
            return;
        }
        int offsetX = getWidth() / mCount / 2;
        int offsetY = getHeight() / 2;
        int radius;

        for (int i = 0; i < mCount; i++) {
            if (i == mCurrentItem % mCount) {

                mPaint.setColor(mSelectedColor);
                radius = mSelectedRadius;
            } else {

                mPaint.setColor(mDefaultColor);
                radius = mDefaultRadius;
            }

            int left = getWidth() * i / mCount + offsetX;
            switch (mIndicatorStyle) {
                case STYLE_RECTANGLE:
                    //长方形
                    canvas.drawRect(left - radius + 1, offsetY - 3, left + radius - 1, offsetY + 3, mPaint);
                    break;
                case STYLE_SQUARE:
                    //正方形
                    canvas.drawRect(left - radius + 1, offsetY - radius + 1, left + radius - 1, offsetY +
                            radius - 1, mPaint);
                    break;
                default:
                    //圆形
                    canvas.drawCircle(left, offsetY, radius, mPaint);
                    break;
            }
        }
    }

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

    }

    @Override
    public void onPageSelected(int position) {

        setCurrentItem(position);
    }

    @Override
    public void onPageScrollStateChanged(int state) {

    }

    public int getCurrentItem() {

        return mCurrentItem;
    }

    public void setCurrentItem(int position) {

        mCurrentItem = position;
        invalidate();
    }

    public void setEnable(boolean enable) {

        mEnable = enable;
        if (mEnable && mCount > 0) {
            startScroll();
        }
    }

    public boolean isEnable() {

        return mEnable;
    }

    public void setAutoScroll(boolean autoScroll) {

        if (mAutoScroll != autoScroll) {
            mAutoScroll = autoScroll;
            if (mAutoScroll) {
                startScroll();
            } else {
                stopScroll();
            }
        }
    }

    public boolean isAutoScroll() {

        return mAutoScroll;
    }

    @Override
    protected void onAttachedToWindow() {

        super.onAttachedToWindow();
        if (mEnable && mCount > 0) {
            startScroll();
        }
    }

    private void startScroll() {

        if (mHandler != null) {
            mHandler.sendEmptyMessageDelayed(0, mScrollIntervalMillis);
        }
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        setAutoScroll(false);
        if (mHandler != null) {
            mHandler.removeCallbacksAndMessages(null);
            mHandler = null;
        }
    }

    private void stopScroll() {

        if (mHandler != null) {
            mHandler.removeCallbacksAndMessages(null);
        }
    }

    private static class CubeTransformer implements ViewPager.PageTransformer {

        /**
         * 当处于最中间的view往左边滑动时，它的position值是小于0的，
         * 并且是越来越小,它右边的view的position是从1逐渐减小到0的。
         */
        @Override
        public void transformPage(View view, float position) {

            /**
             *  立方体
             */
            if (position <= 0) {
                //从右向左滑动为当前View
                //设置旋转中心点；
                view.setPivotX(view.getMeasuredWidth());
                view.setPivotY(view.getMeasuredHeight() * 0.5f);
                view.setRotationY(80f * position);
            } else if (position <= 1) {
                //从左向右滑动为当前View
                view.setPivotX(0);
                view.setPivotY(view.getMeasuredHeight() * 0.5f);
                view.setRotationY(80f * position);
            }
            /**
             * 转盘
             */
            // if (position <= 0) {
            // 	//从右向左滑动为当前View
            // 	//设置旋转中心点；
            // 	view.setPivotX(view.getMeasuredWidth() * 1.0f);
            // 	view.setPivotY(view.getMeasuredHeight() * 1.0f);
            // 	view.setRotation(30f * position);
            // } else if (position <= 1) {
            // 	//从左向右滑动为当前View
            // 	view.setPivotX(view.getMeasuredWidth() * 0.0f);
            // 	view.setPivotY(view.getMeasuredHeight() * 1.0f);
            // 	view.setRotation(30f * position);
            // }
            /**
             * 渐入渐出
             */
            if (position < -1) { // [-Infinity,-1)//This page is way off-screen to the left.
                view.setAlpha(0);
            } else if (position <= 0) { // [-1,0]Use //the default slide transition when moving to the left page
                view.setAlpha(1);
                // view.setTranslationX(0);
                // view.setScaleX(1);
                // view.setScaleY(1);
            } else if (position <= 1) { // (0,1]// Fade the page out.
                view.setAlpha(1 - position);
                // Counteract the default slide transition
                // view.setTranslationX(pageWidth * -position);
                // Scale the page down (between MIN_SCALE and 1)
                // float scaleFactor = 0.75f + (1 - 0.75f) * (1 - Math.abs(position));
                // view.setScaleX(scaleFactor);
                // view.setScaleY(scaleFactor);
            } else { // (1,+Infinity]
                // This page is way off-screen to the right.
                view.setAlpha(0);
            }
            /**
             *左边渐变滑出滑入
             */
            // int pWidth = view.getWidth();
            // int pHeight = view.getHeight();
            //
            // if (position < -1) { // [-Infinity,-1)
            // 	// This page is way off-screen to the left.
            // 	view.setAlpha(0);
            // } else if (position <= 1) { // [-1,1]
            // 	// Modify the default slide transition to
            // 	// shrink the page as well
            // 	float scaleFactor = Math.max(0.85f, 1 - Math.abs(position));
            // 	float vertMargin = pHeight * (1 - scaleFactor) / 2;
            // 	float horzMargin = pWidth * (1 - scaleFactor) / 2;
            // 	if (position < 0) {
            // 		view.setTranslationX(horzMargin - vertMargin / 2);
            // 	} else {
            // 		view.setTranslationX(-horzMargin + vertMargin / 2);
            // 	}
            // 	// Scale the page down (between MIN_SCALE and 1)
            // 	view.setScaleX(scaleFactor);
            // 	view.setScaleY(scaleFactor);
            // 	// Fade the page relative to its size.
            // 	view.setAlpha(0.5f + (scaleFactor - 0.85f) / (1 - 0.85f) * (1 - 0.5f));
            // } else { // (1,+Infinity]
            // 	// This page is way off-screen to the right.
            // 	view.setAlpha(0);
            // }
            /**
             * 缩放进出
             */
            // if (position < -1) {
            // 	position = -1;
            // } else if (position > 1) {
            // 	position = 1;
            // }
            // float tempScale = position < 0 ? 1 + position : 1 - position;
            // float slope = (1.2f - 0.6f) / 1;
            // float scaleValue = 0.6f + tempScale * slope;
            // view.setScaleX(scaleValue);
            // view.setScaleY(scaleValue);
        }
    }

    public static class FixedScroller extends Scroller {

        private int mDurationValue = 1500;

        public FixedScroller(Context context) {

            super(context);
        }

        public FixedScroller(Context context, Interpolator interpolator) {

            super(context, interpolator);
        }

        @Override
        public void startScroll(int startX, int startY, int dx, int dy, int duration) {
            // Ignore received duration, use fixed one instead
            super.startScroll(startX, startY, dx, dy, mDurationValue);
        }

        @Override
        public void startScroll(int startX, int startY, int dx, int dy) {
            // Ignore received duration, use fixed one instead
            super.startScroll(startX, startY, dx, dy, mDurationValue);
        }

        public void setDurationValue(int durationValue) {
            mDurationValue = durationValue;
        }

        public int getDurationValue() {
            return mDurationValue;
        }
    }
}
